Make sure xend start doesn't return until xend is ready to accept connections.
authorshand@ubuntu.eng.hq.xensource.com <shand@ubuntu.eng.hq.xensource.com>
Thu, 15 Sep 2005 01:45:51 +0000 (17:45 -0800)
committershand@ubuntu.eng.hq.xensource.com <shand@ubuntu.eng.hq.xensource.com>
Thu, 15 Sep 2005 01:45:51 +0000 (17:45 -0800)
This means xend start && xm list actually works now (instead of throwing an
exception).

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
tools/misc/xend
tools/python/xen/web/httpserver.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/SrvServer.py

index 1777c6488f7bb7bcbba6f8abb6da0d93c02cd715..e1a6b4f437be5faabc18e6f5f9174f21054e9808 100644 (file)
@@ -86,9 +86,6 @@ def main():
     daemon = SrvDaemon.instance()
     if not sys.argv[1:]:
         print 'usage: %s {start|stop|restart}' % sys.argv[0]
-    elif os.fork():
-        pid, status = os.wait()
-        return status >> 8
     elif sys.argv[1] == 'start':
         start_xenstored()
         start_consoled()
index 6c06e4476444ed1059b4bdbbbb1260c461291a41..394dba2759c38580004b73467060021ef3ac2bb3 100644 (file)
@@ -273,6 +273,9 @@ class HttpServer:
         self.interface = interface
         self.port = port
         self.root = root
+        # ready indicates when we are ready to begin accept connections
+        # it should be set after a successful bind
+        self.ready = False
 
     def getRoot(self):
         return self.root
@@ -283,6 +286,7 @@ class HttpServer:
     def run(self):
         self.bind()
         self.listen()
+        self.ready = True
         self.requestLoop()
 
     def stop(self):
index c8fc1ff3840d2399858044dcf26aaab59caf590a..378497e5574973b52b1e085e6a87e4fc00258250 100644 (file)
@@ -137,13 +137,6 @@ class Daemon:
         else:
             return 0
 
-    def onSIGCHLD(self, signum, frame):
-        if self.child > 0: 
-            try: 
-                pid, sts = os.waitpid(self.child, os.WNOHANG)
-            except os.error, ex:
-                pass
-
     def fork_pid(self, pidfile):
         """Fork and write the pid of the child to 'pidfile'.
 
@@ -200,15 +193,29 @@ class Daemon:
             # Trying to run an already-running service is a success.
             return 0
 
-        signal.signal(signal.SIGCHLD, self.onSIGCHLD)
+        ret = 0
+
+        # we use a pipe to communicate between the parent and the child process
+        # this way we know when the child has actually initialized itself so
+        # we can avoid a race condition during startup
+        
+        r,w = os.pipe()
         if self.fork_pid(XEND_PID_FILE):
-            #Parent. Sleep to give child time to start.
-            time.sleep(1)
+            os.close(w)
+            r = os.fdopen(r, 'r')
+            s = r.read()
+            r.close()
+            if not len(s):
+                ret = 1
+            else:
+                ret = int(s)
         else:
+            os.close(r)
             # Child
             self.tracing(trace)
-            self.run()
-        return 0
+            self.run(os.fdopen(w, 'w'))
+
+        return ret
 
     def tracing(self, traceon):
         """Turn tracing on or off.
@@ -290,7 +297,7 @@ class Daemon:
     def stop(self):
         return self.cleanup(kill=True)
 
-    def run(self):
+    def run(self, status):
         _enforce_dom0_cpus()
         try:
             log.info("Xend Daemon started")
@@ -298,12 +305,14 @@ class Daemon:
             relocate.listenRelocation()
             servers = SrvServer.create()
             self.daemonize()
-            servers.start()
+            servers.start(status)
         except Exception, ex:
             print >>sys.stderr, 'Exception starting xend:', ex
             if XEND_DEBUG:
                 traceback.print_exc()
             log.exception("Exception starting xend (%s)" % ex)
+            status.write('1')
+            status.close()
             self.exit(1)
             
     def exit(self, rc=0):
index 12a2f5ff5c3a797d70fafc33e09b6b51f7ea81d0..ecd4975728baadf75626952d5cd6d6f2ef320d79 100644 (file)
@@ -48,6 +48,7 @@ from xen.xend import XendRoot; xroot = XendRoot.instance()
 from xen.xend import Vifctl
 from xen.xend.XendLogging import log
 from xen.web.SrvDir import SrvDir
+import time
 
 from SrvRoot import SrvRoot
 
@@ -59,7 +60,7 @@ class XendServers:
     def add(self, server):
         self.servers.append(server)
 
-    def start(self):
+    def start(self, status):
         Vifctl.network('start')
         threads = []
         for server in self.servers:
@@ -67,6 +68,25 @@ class XendServers:
             thread.start()
             threads.append(thread)
 
+
+        # check for when all threads have initialized themselves and then
+        # close the status pipe
+
+        threads_left = True
+        while threads_left:
+            threads_left = False
+
+            for server in self.servers:
+                if not server.ready:
+                    threads_left = True
+                    break
+
+            if threads_left:
+                time.sleep(.5)
+
+        status.write('0')
+        status.close()
+
         for t in threads:
             t.join()